program WebSocketChatServer;

{$APPTYPE CONSOLE}

uses
  System.SysUtils,
  System.IOUtils,
  IdHTTPWebBrokerBridge,
  Web.WebReq,
  Web.WebBroker,
  MVCFramework,
  MVCFramework.Commons,
  MVCFramework.Logger,
  MVCFramework.Serializer.Commons,
  MVCFramework.WebSocket,
  MVCFramework.WebSocket.Server,
  WebModuleU in 'WebModuleU.pas' {WebModule1: TWebModule};

var
  LWebServer: TIdHTTPWebBrokerBridge;
  LWSServer: TMVCWebSocketServer;

begin
  { Enable ReportMemoryLeaksOnShutdown during debug }
  // ReportMemoryLeaksOnShutdown := True;
  IsMultiThread := True;

  // DMVCFramework Specific Configurations
  //   When MVCSerializeNulls = True empty nullables and nil are serialized as json null.
  //   When MVCSerializeNulls = False empty nullables and nil are not serialized at all.
  MVCSerializeNulls := True;

  // MVCNameCaseDefault defines the name case of property names generated by the serializers.
  //   Possibile values are: ncAsIs, ncUpperCase, ncLowerCase (default), ncCamelCase, ncPascalCase, ncSnakeCase
  MVCNameCaseDefault := TMVCNameCase.ncLowerCase;

  // UseConsoleLogger defines if logs must be emitted to also the console (if available).
  UseConsoleLogger := True;

  // UseLoggerVerbosityLevel defines the lowest level of logs that will be produced.
  UseLoggerVerbosityLevel := TLogLevel.levNormal;


  LogI('** DMVCFramework Server ** build ' + DMVCFRAMEWORK_VERSION);


  ReportMemoryLeaksOnShutdown := True;


  if WebRequestHandler <> nil then
    WebRequestHandler.WebModuleClass := WebModuleClass;

  WebRequestHandlerProc.MaxConnections := dotEnv.Env('dmvc.handler.max_connections', 1024);


  Randomize;

  try
    Writeln('=======================================================');
    Writeln('    DMVCFramework WebSocket Chat Demo');
    Writeln('=======================================================');
    Writeln('');

    // Start HTTP server for serving web client
    Writeln('Starting HTTP server on port 8080...');
    LWebServer := TIdHTTPWebBrokerBridge.Create(nil);
    try
      LWebServer.DefaultPort := 8080;
      LWebServer.Active := True;
      Writeln('  -> HTTP server running at http://localhost:8080/');
      Writeln('');

      // Start WebSocket server
      Writeln('Starting WebSocket server on port 9091...');
      LWSServer := TMVCWebSocketServer.Create(9091);
      try
        // Setup event handlers
        LWSServer.OnLog := procedure(const AMessage: string)
        begin
          Writeln(Format('[%s] %s', [TimeToStr(Now), AMessage]));
        end;

        // Handle incoming text messages - broadcast to all clients
        LWSServer.OnMessage := procedure(AClient: TWebSocketClient; const AMessage: string)
        var
          LChatMsg: string;
        begin
          Writeln(Format('[%s] <%s> %s', [TimeToStr(Now), AClient.Username, AMessage]));
          // Format and broadcast message to all clients
          LChatMsg := Format('[%s]: %s', [AClient.Username, AMessage]);
          AClient.Broadcast(LChatMsg);
        end;

        // Handle client connection - send welcome message to all
        LWSServer.OnClientConnect := procedure(AClient: TWebSocketClient)
        var
          LWelcomeMsg: string;
        begin
          LWelcomeMsg := Format('[SERVER]: %s joined the chat (%d users online)',
            [AClient.Username, AClient.ConnectedUsersCount]);
          AClient.Broadcast(LWelcomeMsg);
        end;

        // Handle client disconnection - notify remaining users
        LWSServer.OnClientDisconnect := procedure(AClient: TWebSocketClient)
        var
          LGoodbyeMsg: string;
        begin
          LGoodbyeMsg := Format('[SERVER]: %s left the chat (%d users online)',
            [AClient.Username, AClient.ConnectedUsersCount - 1]); // -1 because not removed yet
          AClient.BroadcastToPeers(LGoodbyeMsg);
        end;

        LWSServer.OnError := procedure(AClient: TWebSocketClient; const AError: string)
        begin
          Writeln(Format('[%s] ERROR from %s: %s', [TimeToStr(Now), AClient.Username, AError]));
        end;

        LWSServer.Active := True;
        Writeln('  -> WebSocket server running at ws://localhost:9091/');
        Writeln('');

        Writeln('=======================================================');
        Writeln('  READY! Open your browser to:');
        Writeln('  http://localhost:8080/');
        Writeln('=======================================================');
        Writeln('');
        Writeln('Features:');
        Writeln('  - Beautiful web-based chat interface');
        Writeln('  - Real-time message broadcasting');
        Writeln('  - User join/leave notifications');
        Writeln('  - Online user counter');
        Writeln('  - Responsive design');
        Writeln('');
        Writeln('Press ENTER to stop both servers...');
        Writeln('');

        Readln;

        Writeln('Stopping servers...');

      finally
        LWSServer.Free;
      end;

    finally
      LWebServer.Free;
    end;

    Writeln('Done.');

  except
    on E: Exception do
    begin
      Writeln('ERROR: ' + E.ClassName + ': ' + E.Message);
      Readln;
      ExitCode := 1;
    end;
  end;
end.
